<template>
    <div>
        <!-- 面包屑导航区域 -->
        <el-breadcrumb separator-class="el-icon-arrow-right">
            <el-breadcrumb-item>集群管理</el-breadcrumb-item>
            <el-breadcrumb-item :to="{ path: '/cluster' }">集群信息列表</el-breadcrumb-item>
            <el-breadcrumb-item>添加 {{ clusterModel.nodes.length > 0 ? 'Standby' : 'Master' }} 节点</el-breadcrumb-item>
        </el-breadcrumb>

        <!-- 内容滚动主体区 -->
        <div :style="innerStyle">

            <el-scrollbar style="height: 100%">
                <el-carousel :height="(getInnerSize.height - 215) + 'px'" :autoplay="false" arrow="never" indicator-position="none" :loop="false" ref="carouselRef" @change="carouselChange">

                    <!-- Page1 节点信息输入 -->
                    <el-carousel-item key="nodePage">
                        <div class="form-div">
                            <div>
                                <el-card shadow="none">
                                    <div slot="header">
                                        <span><i class="el-icon-info"></i> 集群信息</span>
                                    </div>
                                    <el-form :model="nodeForm" ref="nodeFormRef" :rules="nodeFormRules" label-width="150px">
                                        <el-form-item label="集群ID">
                                            <el-input v-model="clusterModel.id" disabled></el-input>
                                        </el-form-item>
                                        <el-form-item label="集群名称">
                                            <el-input v-model="clusterModel.name" disabled></el-input>
                                        </el-form-item>
                                        <el-form-item label="系统普通用户名">
                                            <el-input v-model="clusterModel.user_normal" disabled></el-input>
                                        </el-form-item>
                                        <el-form-item label="数据库安装目录">
                                            <el-input v-model="clusterModel.installation_path" disabled></el-input>
                                        </el-form-item>
                                        <el-form-item label="信任网关">
                                            <el-tag v-for="tag in clusterModel.trust_servers" :key="tag">
                                                {{tag}}
                                            </el-tag>
                                        </el-form-item>
                                        <el-form-item label="数据库管理员用户">
                                            <el-input v-model="clusterModel.db_user" disabled></el-input>
                                        </el-form-item>
                                        <el-form-item label="兼容模式">
                                            <el-input v-model="clusterModel.db_mode" disabled></el-input>
                                        </el-form-item>
                                        <el-form-item label="虚拟IP地址">
                                            <el-tag>{{clusterModel.virtual_ip}}</el-tag>
                                        </el-form-item>
                                    </el-form>
                                </el-card>
                            </div>
                            <div>
                                <el-card shadow="none">
                                    <div slot="header">
                                        <span><i class="el-icon-share"></i> 节点信息</span>
                                    </div>
                                    <div v-for="node in clusterModel.nodes" :key="node.id">
                                        <el-tag type="primary"><i class="el-icon-star-on"></i> 节点ID：{{node.id}} </el-tag>
                                        <el-tag type="primary"><i class="el-icon-info"></i> 节点名称：{{node.name}} </el-tag>
                                        <el-tag type="primary"><i class="el-icon-success"></i> 节点地址：{{node.ipaddr}} </el-tag>
                                    </div>
                                </el-card>
                                <el-card class="box-card" shadow="always">
                                    <div slot="header">
                                        <span><i class="el-icon-edit-outline"></i> 添加节点</span>
                                    </div>
                                    <el-form :model="nodeForm" ref="nodeFormRef" :rules="nodeFormRules" label-width="150px">
                                        <el-form-item label="数据库节点名称" prop="name">
                                            <el-input prefix-icon="el-icon-edit" v-model="nodeForm.name" maxlength="30" show-word-limit></el-input>
                                        </el-form-item>
                                        <el-form-item label="数据库节点地址" prop="ipaddr">
                                            <el-input prefix-icon="el-icon-edit" v-model="nodeForm.ipaddr"></el-input>
                                        </el-form-item>
                                        <el-form-item label="证书文件路径" prop="license_path">
                                            <el-input prefix-icon="el-icon-edit" v-model="nodeForm.license_path" readonly>
                                                <el-button slot="append" icon="el-icon-folder-opened"></el-button>
                                            </el-input>
                                        </el-form-item>
                                    </el-form>
                                </el-card>
                            </div>
                        </div>
                    </el-carousel-item>

                    <!-- Page2 节点有效性及环境需求校验 -->
                    <el-carousel-item key="validatePage">
                        <div class="validate-div" :style="'height: '+ (getInnerSize.height - 215) + 'px; overflow: auto;'">
                            <el-card class="card-timeline">
                                <div slot="header">
                                    <span>节点检测流程</span>
                                </div>
                                <el-timeline>
                                    <el-timeline-item
                                        v-for="(activity, index) in processCheckingInfo.activities"
                                        :key="index"
                                        :icon="activity.icon"
                                        :type="activity.type"
                                        :color="activity.color"
                                        :size="activity.size"
                                        :timestamp="activity.timestamp">
                                        {{activity.content}}
                                    </el-timeline-item>
                                </el-timeline>
                            </el-card>

                            <el-card class="card-timemessage">
                                <div slot="header">
                                    <span>节点有效性及环境需求校验日志</span>
                                    <div :style="'float: right; color: ' + processCheckingInfo.titleColor + ';'">
                                        <i :class="processCheckingInfo.titleIcon"></i>
                                        {{processCheckingInfo.titleName}}
                                        <el-button :style="processCheckingInfo.titleStyle" type="danger" icon="el-icon-more" size="mini" circle></el-button>
                                    </div>
                                </div>
                                <div class="div-timemessage" :style="'height: ' + (getInnerSize.height - 335) + 'px'">
                                    <textarea
                                        v-model="processCheckingInfo.log" 
                                        style="outline: none; border: none; resize: none; width: 100%; height: 100%; font-size: 12px; font-family: 'Courier New', Courier, monospace;" 
                                        readonly>
                                    </textarea>
                                </div>
                            </el-card>
                        </div>
                    </el-carousel-item>

                    <!-- Page3 集群及节点信息预览确认 -->
                    <el-carousel-item key="infoPage">
                        <div class="info-div">
                            <div>
                                <div class="info-normal">
                                    <el-divider content-position="left"><i class="el-icon-info"></i> 数据库参数</el-divider>
                                    <textarea readonly v-model="params_normal"></textarea>
                                </div>
                                <div class="info-advanced">
                                    <el-divider content-position="left"><i class="el-icon-s-claim"></i> HA高可用参数</el-divider>
                                    <textarea readonly v-model="params_advanced"></textarea>
                                </div>
                            </div>
                            <div>
                                <div class="info-basic">
                                    <el-divider content-position="left"><i class="el-icon-s-data"></i> 集群参数</el-divider>
                                    <textarea readonly v-model="params_basic"></textarea>
                                </div>
                                <div class="info-node">
                                    <el-divider content-position="left"><i class="el-icon-star-on"></i> 新增节点参数</el-divider>
                                    <textarea readonly v-model="params_node"></textarea>
                                </div>
                            </div>
                        </div>
                    </el-carousel-item>
                </el-carousel>
            </el-scrollbar>
        </div>

        <div class="div-submit">
            <el-button type="danger" icon="el-icon-caret-left" @click="cancel">取 消</el-button>
            <el-button type="primary" icon="el-icon-back" @click="previousStep" :disabled="pageStepNo <= 0 || inJobProcessing">上一步</el-button>
            <el-button type="primary" @click="nextStep" :disabled="!nextStepEnable">下一步<i class="el-icon-right el-icon--right"></i></el-button>
            <el-button type="success" icon="el-icon-finished" @click="deployNode" :disabled="pageStepNo <= 1">确 定</el-button>
        </div>

        <!-- 节点部署对话框 -->
        <el-dialog :title="`数据库集群节点部署`" 
            :visible.sync="installationDialogVisible" 
            :before-close="installationHandleClose"
            :show-close="false"
            width="90%">
            
            <div class="installation-div">
                <el-card class="card-timeline">
                    <div slot="header">
                        <span>节点部署流程</span>
                    </div>

                    <div style="height: 485px; overflow: auto;">
                        <el-timeline>
                            <el-timeline-item
                                v-for="(activity, index) in processInstallingInfo.activities"
                                :key="index"
                                :icon="activity.icon"
                                :type="activity.type"
                                :color="activity.color"
                                :size="activity.size"
                                :timestamp="activity.timestamp">
                                {{activity.content}}
                            </el-timeline-item>
                        </el-timeline>
                    </div>
                </el-card>

                <el-card class="card-timemessage">
                    <div slot="header">
                        <span>节点部署流程日志</span>
                        <div :style="'float: right; color: ' + processInstallingInfo.titleColor + ';'">
                            <i :class="processInstallingInfo.titleIcon"></i>
                            {{processInstallingInfo.titleName}}
                            <el-button :style="processInstallingInfo.titleStyle" type="danger" icon="el-icon-more" size="mini" circle></el-button>
                        </div>
                    </div>
                    <div class="div-timemessage" :style="'height: 480px;'">
                        <textarea
                            v-model="processInstallingInfo.log" 
                            style="word-wrap:normal; outline: none; border: none; resize: none; width: 100%; height: 100%; font-size: 12px; font-family: 'Courier New', Courier, monospace;" 
                            readonly>
                        </textarea>
                    </div>
                </el-card>
            </div>

            <span slot="footer" class="dialog-footer">
                <el-button type="primary" @click="finish" :disabled="(jobData[1].status === 0 || jobData[1].status === 1)">确 定</el-button>
            </span>
        </el-dialog>

    </div>
</template>

<script>
import { mapGetters } from 'vuex';
export default {
    data: function () {
        var checkNodeName = async (rule, value, callback) => {
            const result = await this.$http.get('nodes', {
                params: { cid: this.clusterModel.id }
            });
            const res = result.data;
            if (res.meta.status !== 200) {
                callback(new Error(`查询集群节点列表失败：${res.meta.msg}`));
            } else if (res.data.nodes.some(item => item.name === value)) {
                callback(new Error(`节点名称 ${value} 已存在！`));
            } else {
                callback();
            }
        }
        var checkIpAddr = async (rule, value, callback) => {
            var ipCheckResult = this.$check_IpAddr(value);
            if (ipCheckResult) {
                callback(new Error(ipCheckResult));
            } else {
                const result = await this.$http.get('nodes', {
                    params: { cid: this.clusterModel.id }
                });
                const res = result.data;
                if (res.meta.status !== 200) {
                    callback(new Error(`查询集群节点列表失败：${res.meta.msg}`));
                } else if (res.data.nodes.some(item => item.ipaddr === value)) {
                    callback(new Error(`地址 ${value} 已存在！`));
                } else {
                    callback();
                }
            }
        }
        return {
            pageStepNo: 0,
            clusterModel: {
                nodes: []
            },
            nodeForm: {
                id: '',
                cid: '',
                name: '',
                ipaddr: '',
                license_path: 'D:/Software Engineering/repository_git/Gitee/Projects/e-repmgr-ha-tools.com/e-repmgr-ha-tools-server/commons/license'
            },
            nodeFormRules: {
                name: [
                    { required: true, message: '请输入节点名称', trigger: 'blur' },
                    { min: 3, max: 30, message: '节点名称的长度在 3 ~ 30 个字符之间', trigger: 'blur' },
                    { validator: checkNodeName, trigger: 'blur' }
                ],
                ipaddr: [
                    { required: true, message: '请输入节点IP地址', trigger: 'blur' },
                    { validator: checkIpAddr, trigger: 'blur' }
                ],
                license_path: [
                    { required: true, message: '请指定license位置', trigger: 'blur' },
                ]
            },
            installationDialogVisible: false,
            inJobProcessing: false,
            jobData: [
                {
                    jobid: '0',
                    status: 0,
                    steps: [
                        {
                            name: '正在准备环境检查事务...',
                            message: '即将开始检测节点环境，请稍候...',
                            status: 0
                        }
                    ]
                }, {
                    jobid: '0',
                    status: 0,
                    steps: [
                        {
                            name: '正在准备节点部署事务...',
                            message: '即将开始部署集群节点，请稍候...',
                            status: 0
                        }
                    ]
                }
            ],
            fullscreenLoading: false
        }
    },
    computed: {
        ...mapGetters(['getInnerSize']),
        innerStyle: function () {
            return `height: ${this.getInnerSize.height - 215}px; overflow: auto;`;
        },
        params_normal: function () {
            let paramsInfo = '';
            paramsInfo += `集群ID：${this.clusterModel.id}\n`;
            paramsInfo += `集群名称：${this.clusterModel.name}\n`;
            paramsInfo += `SSH监听端口：${this.clusterModel.ssh_port}\n`;
            paramsInfo += `系统普通用户名：${this.clusterModel.user_normal}\n`;
            paramsInfo += `系统管理员密码：${this.clusterModel.root_password}\n`;
            paramsInfo += `数据库安装路径：${this.clusterModel.installation_path}\n`;
            paramsInfo += `归档文件目录：${this.clusterModel.archive_path}\n`;
            paramsInfo += `信任网关：${this.clusterModel.trust_servers}\n`;
            paramsInfo += `HA日志文件：${this.clusterModel.log_file}\n`;
            paramsInfo += `数据库data目录：${this.clusterModel.data_directory}\n`;
            paramsInfo += `数据库bin目录：${this.clusterModel.pg_bin_dir}\n`;
            paramsInfo += `HA PID文件：${this.clusterModel.hamgr_pid_file}\n`;

            return paramsInfo;
        },
        params_basic: function () {
            let paramsInfo = '';
            paramsInfo += `最大连接数：${this.clusterModel.max_connections}\n`;
            paramsInfo += `数据库监听端口：${this.clusterModel.db_port}\n`;
            paramsInfo += `数据库管理员用户：${this.clusterModel.db_user}\n`;
            paramsInfo += `数据库用户密码：${this.clusterModel.db_password}\n`;
            paramsInfo += `复制模式：${this.clusterModel.replication_mode}\n`;
            paramsInfo += `兼容模式：${this.clusterModel.db_mode}\n`;
            paramsInfo += `加密方式：${this.clusterModel.encryption}\n`;
            paramsInfo += `HA库名称：${this.clusterModel.hamgr_dbname}\n`;
            paramsInfo += `HA库用户：${this.clusterModel.hamgr_dbuser}\n`;
            paramsInfo += `ping命令路径：${this.clusterModel.ping_path}\n`;

            return paramsInfo;
        },
        params_advanced: function () {
            let paramsInfo = '';
            paramsInfo += `备服务器WAL文件数：${this.clusterModel.wal_keep_segments}\n`;
            paramsInfo += `进程最大数：${this.clusterModel.max_wal_senders}\n`;
            paramsInfo += `热备反馈：${this.clusterModel.hot_standby_feedback}\n`;
            paramsInfo += `编码格式：${this.clusterModel.server_encoding}\n`;
            paramsInfo += `虚拟IP地址：${this.clusterModel.virtual_ip}\n`;
            paramsInfo += `虚拟子网掩码：${this.clusterModel.virtual_ip_mask}\n`;
            paramsInfo += `arping命令路径：${this.clusterModel.arping_path}\n`;
            paramsInfo += `ip命令路径：${this.clusterModel.ip_path}\n`;
            paramsInfo += `SSH 参数：${this.clusterModel.ssh_options}\n`;
            paramsInfo += `重连尝试次数：${this.clusterModel.reconnect_attempts}\n`;
            paramsInfo += `重连次数间隔：${this.clusterModel.reconnect_interval}\n`;
            paramsInfo += `故障转移方式：${this.clusterModel.failover}\n`;
            paramsInfo += `恢复方式：${this.clusterModel.recovery}\n`;

            return paramsInfo;
        },
        params_node: function () {
            let paramsInfo = '';
            paramsInfo += `节点名称：${this.nodeForm.name}\n`;
            paramsInfo += `节点IP地址：${this.nodeForm.ipaddr}\n`;
            paramsInfo += `许可证文件路径：${this.nodeForm.license_path}\n`;

            return paramsInfo;
        },
        processCheckingInfo: function () {
            const activities = [];
            let logContent = '';
            let titleName = '节点环境校验即将开始';
            const stepsCount = this.jobData[0].steps.length;
            for (let i = 0; i < stepsCount; i++) {
                const statusCode = this.jobData[0].steps[i].status;
                let iconName = '';
                let colorVal = '#E4E7ED';
                let timestamp= '';
                if (statusCode === -1) {
                    // 中断
                    iconName = 'el-icon-error';
                    colorVal = '#FF0000';
                    timestamp = '执行错误';

                } else if (statusCode === 0) {
                    // 等待执行
                    iconName = 'el-icon-remove';
                    colorVal = '#E4E7ED';
                    timestamp = '等待执行';

                } else if (statusCode === 1) {
                    // 活动中
                    iconName = 'el-icon-loading';
                    colorVal = '#40AAFF';
                    timestamp = '正在执行';
                    titleName = this.jobData[0].steps[i].name;

                } else if (statusCode === 2) {
                    // 完成
                    iconName = 'el-icon-success';
                    colorVal = '#67C23A';
                    timestamp = '执行成功';
                }
                activities.push({
                    content: this.jobData[0].steps[i].name,
                    size: 'large',
                    icon: iconName,
                    color: colorVal,
                    timestamp: timestamp
                });
                if (statusCode !== 0) {
                    logContent += ` (${i + 1}/${stepsCount}) ${this.jobData[0].steps[i].name} \n`;
                    logContent += `${this.jobData[0].steps[i].message}\n\n`;
                    // logContent += `步骤状态：${this.jobData[0].steps[i].status}\n\n`;
                }
            }
            let titleIcon = 'el-icon-loading';
            let titleColor = '#E4E7ED';
            let titleStyle = 'display: none;';
            const statusCode = this.jobData[0].status;
            if (statusCode === -1) {
                titleIcon = "el-icon-close";
                titleColor = '#FF0000';
                titleName = '节点环境校验失败';
                titleStyle = 'display: inline;';
            } else if (statusCode === 0) {
                titleIcon = "el-icon-warning-outline";
                titleColor = '#E4E7ED';
            } else if (statusCode === 1) {
                titleIcon = "el-icon-loading";
                titleColor = '#40AAFF';
            } else if (statusCode === 2) {
                titleIcon = "el-icon-check";
                titleName = '节点环境校验成功';
                titleColor = '#67C23A';
            } else {
                titleIcon = "el-icon-minus";
            }
            return {
                activities: activities,
                log: logContent,
                titleIcon: titleIcon,
                titleName: titleName,
                titleColor: titleColor,
                titleStyle: titleStyle
            };
        },
        processInstallingInfo: function () {
            const activities = [];
            let logContent = '';
            let titleName = '节点部署即将开始';
            const stepsCount = this.jobData[1].steps.length;
            for (let i = 0; i < stepsCount; i++) {
                const statusCode = this.jobData[1].steps[i].status;
                let iconName = '';
                let colorVal = '#E4E7ED';
                let timestamp= '';
                if (statusCode === -1) {
                    // 中断
                    iconName = 'el-icon-error';
                    colorVal = '#742A25';
                    timestamp = '执行错误';

                } else if (statusCode === 0) {
                    // 等待执行
                    iconName = 'el-icon-remove';
                    colorVal = '#E4E7ED';
                    timestamp = '等待执行';

                } else if (statusCode === 1) {
                    // 活动中
                    iconName = 'el-icon-loading';
                    colorVal = '#40AAFF';
                    timestamp = '正在执行';
                    titleName = this.jobData[1].steps[i].name;

                } else if (statusCode === 2) {
                    // 完成
                    iconName = 'el-icon-success';
                    colorVal = '#00FF00';
                    timestamp = '执行成功';
                }
                activities.push({
                    content: this.jobData[1].steps[i].name,
                    size: 'large',
                    icon: iconName,
                    color: colorVal,
                    timestamp: timestamp
                });

                if (statusCode !== 0) {
                    logContent += ` (${i + 1}/${stepsCount}) ${this.jobData[1].steps[i].name} \n`;
                    logContent += `${this.jobData[1].steps[i].message}\n\n`;
                    // logContent += `步骤状态：${this.jobData[1].steps[i].status}\n\n`;
                }
            }
            let titleIcon = 'el-icon-loading';
            let titleColor = '#E4E7ED';
            let titleStyle = 'display: none;';
            const statusCode = this.jobData[1].status;
            if (statusCode === -1) {
                titleIcon = "el-icon-close";
                titleColor = '#FF0000';
                titleName = '集群节点部署失败';
                titleStyle = 'display: inline;';
            } else if (statusCode === 0) {
                titleIcon = "el-icon-warning-outline";
                titleColor = '#E4E7ED';
            } else if (statusCode === 1) {
                titleIcon = "el-icon-loading";
                titleColor = '#40AAFF';
            } else if (statusCode === 2) {
                titleIcon = "el-icon-check";
                titleName = '集群节点部署完成';
                titleColor = '#67C23A';
            } else {
                titleIcon = "el-icon-minus";
            }
            return {
                activities: activities,
                log: logContent,
                titleIcon: titleIcon,
                titleName: titleName,
                titleColor: titleColor,
                titleStyle: titleStyle
            };
        },
        nextStepEnable: function () {
            if (this.pageStepNo === 0) {
                return true;
            } else if (this.pageStepNo === 1) {
                if (this.inJobProcessing || this.jobData[0].status !== 2) return false;
                return true;
            } else {
                return false;
            }
        }
    },
    mounted: function () {
        this.clusterModel = this.$route.query.clusterModel;
        this.nodeForm.cid = this.clusterModel.id;
    },
    methods: {
        cancel: function () {
            this.$router.push('/cluster');
        },
        previousStep: function () {
            if (this.pageStepNo <= 0) return;
            this.pageStepNo -= 1;
            this.$refs.carouselRef.setActiveItem(this.pageStepNo)
        },
        nextStep: function () {
            if (this.pageStepNo <= 0) {
                this.$refs.nodeFormRef.validate(async valid => {
                    if (!valid) return this.$message.error(`节点信息填写不正确，请将校验失败的信息修改正确后再次尝试...`);
                    else {
                        if (this.pageStepNo >= 2) return;
                        this.pageStepNo += 1;
                        this.$refs.carouselRef.setActiveItem(this.pageStepNo);

                        this.inJobProcessing = true;
                        const msgPreparation = await this.addNodePreparation();
                        if (msgPreparation) {
                            this.$message.error(`节点有效性及环境需求校验过程中发生错误：${msgPreparation}`);
                            this.inJobProcessing = false;
                            return;
                        }
                        this.getProcessResult(0);
                    }
                });
            } else {
                if (this.pageStepNo >= 2) return;
                this.pageStepNo += 1;
                this.$refs.carouselRef.setActiveItem(this.pageStepNo)
            }
        },
        deployNode: async function () {
            const rm = await this.$confirm('即将开始部署数据库集群节点，是否继续？', '确认', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'question'
            }).catch(err => err);
            if (rm !== 'confirm') return this.$message.info('已取消节点创建。');

            // 1.0 lowdb节点数据创建
            const addDataMsg = await this.addNodeData();
            if (addDataMsg) return this.$message.error(`添加节点数据失败：${addDataMsg}`);

            // 2.0 发送任务处理流程委托
            const msgInstallation = await this.addNodeInstallation();
            if (msgInstallation) return this.$message.error(`集群节点部署过程中发生错误: ${msgInstallation}`);

            // 3.0 显示部署对话框，并添加后台任务轮询
            this.installationDialogVisible = true;
            this.getProcessResult(1);
        },
        installationHandleClose: function () {},
        carouselChange: function () {},
        addNodeData: async function () {
            const result = await this.$http.post('nodes', this.nodeForm);
            const res = result.data;
            if (res.meta.status !== 201) return res.meta.msg;
            this.nodeForm.id = res.data.id;
            return '';
        },
        getProcessResult: function (jobDataIndex) {
            setTimeout(async () => {
                // 4c1d4dd8-c593-4975-8f03-1fe9c27563c5
                const result = await this.$http.get(`process/${this.jobData[jobDataIndex].jobid}`);
                const res = result.data;
                if (res.meta.status !== 201) return this.$message.error(`获取任务处理信息失败：${res.meta.msg}`);
                this.$set(this.jobData, jobDataIndex, res.data);

                // 任务如果非错误和完成状态，则循环监听任务回执消息
                const statusCode = res.data.status;
                if (statusCode !== -1 && statusCode !== 2) this.getProcessResult(jobDataIndex);
                else this.inJobProcessing = false;
            }, 2000);
        },
        // 节点部署准备
        addNodePreparation: async function () {
            const result = await this.$http.post(`nodes/preparation`, {
                cid: this.clusterModel.id,
                ipaddr: this.nodeForm.ipaddr
            });
            const res = result.data;
            if (res.meta.status !== 201) return res.meta.msg;
            this.jobData[0].jobid = res.data.job_id;
        },
        // 节点正式部署
        addNodeInstallation: async function () {
            const result = await this.$http.post(`nodes/deployment/${this.clusterModel.id}`);
            const res = result.data;
            if (res.meta.status !== 201) return res.meta.msg;
            this.jobData[1].jobid = res.data.job_id;
            console.log("节点部署：", this.jobData[1].jobid);
        },
        finish: function () {
            this.installationDialogVisible = false;
            if (this.jobData[1].status === 2) return this.$router.push('/cluster');
        }
    }
}
</script>

<style lang="less" scoped>
    .form-div {
        display: flex;
    }

    .el-tag {
        margin-right: 10px;
    }

    // 第一屏
    .form-div > div {
        flex: 1;
    }

    .form-div .el-card {
        margin: 10px;
    }

    // 第二屏
    .validate-div {
        display: flex;
    }

    .validate-div .card-timeline {
        width: 300px;
        margin: 10px;
    }

    .validate-div .card-timemessage {
        flex: 1;
        margin: 10px;
    }

    // 第三屏
    .info-div {
        display: flex;
        height: 100%;
    }

    .info-div > div {
        flex: 1;
    }

    .info-div .info-normal,
    .info-div .info-basic {
        height: 40%;
        margin: 0 15px;
    }
    .info-div .info-advanced,
    .info-div .info-node {
        height: 60%;
        margin: 0 15px;
    }

    .info-div textarea {
        outline: none;
        border: none;
        resize: none;
        width: 100%;
        height: calc(100% - 20px);
        font-size: 14px;
        font-family: 'Courier New', Courier, monospace;
    }

    // 部署对话框
    .installation-div {
        display: flex;
        height: 590px;
    }

    .installation-div .card-timeline {
        width: 300px;
        margin: 10px;
    }

    .installation-div .card-timemessage {
        flex: 1;
        margin: 10px;
    }

    .div-submit {
        margin-top: 15px;
        display: flex;
        width: 100%;
        justify-content: center;
    }
</style>